#!/bin/sh
#
# This script generates a project-wide version identifier for use by
# the `elftc_version()' API.
#
# $Id: make-toolchain-version 4023 2023-12-09 14:41:43Z jkoshy $

#
# Defaults.
#
buildhost=`uname -s`
elftcname="elftoolchain"
options="e:h:o:pr:t:"
top=""
version="HEAD"
versionfile="elftc_version.c"
progname=`basename ${0}`

usage()
{
    exec >&2

    # Print a message, if supplied.
    if [ -n "${*}" ]; then echo "## ${@}"; fi

    echo "Usage: ${progname} -t TOPDIR [options]"
    echo "	Generate a toolchain-wide version number"
    echo "	-e PROJECTNAME Set the project name [default: ${elftcname}]."
    echo "	-h HOSTOS      Set the build OS [default: ${buildhost}]."
    echo "	-o OUTPUT      Set the output file [default: ${versionfile}]."
    echo "	-p             Write a plain version string to output."
    echo "	-r VERSION     Set the version string [default: ${version}]."
    echo "	-t TOPDIR      Set the top-of-tree directory [required]."
    exit 1
}

# Determine the revision number for the source tree.
#
# - If CVS is detected, we use the string `unknown'.
# - If SVN is detected, we use the `svninfo' tool to determine the
#   in-tree revision number.
# - Otherwise, we use `git --describe'.
get_revision_string()
{
    v="unknown:unknown"
    if [ -d CVS ]; then     # Look for CVS (NetBSD).
        v="cvs:unknown"
    elif [ -d .svn -o -d ../.svn ]; then
	# An SVN checkout (SourceForge or FreeBSD prior to r368820).
        svnversion="$(svnversion 2>/dev/null)"
        if [ -n "${svnversion}" ]; then
            v="svn:${svnversion}"
        fi
    else        # Try git (DragonflyBSD, FreeBSD).
        gitversion="$(git describe --all --dirty --long 2> /dev/null)"
        if [ -n "${gitversion}" ]; then
            v="git:${gitversion}"
	fi
    fi

    echo "${v}"
}

#
# Parse options.
#

while getopts ${options} option
do
    case ${option} in
	'e') elftcname="${OPTARG}"   ;;
	'h') buildhost="${OPTARG}"   ;;
	'o') versionfile="${OPTARG}" ;;
	'r') version="${OPTARG}"     ;;
	'p') plain_version_string=true ;;
	't') top="${OPTARG}"         ;;
	'?') usage                   ;;
    esac
done

[ -n "${top}" ] || usage "The -t flag was not specified."

curdir=`pwd`
cd ${top} || usage "ERROR: Cannot change directory to \"${top}\"."

# Determine the in-tree revision number.
versionstring="$(get_revision_string)"

# Prepare the full toolchain version string.
toolchain_version="${elftcname} ${version} ${buildhost} ${versionstring}"

cd ${curdir} || usage "Cannot change back to ${curdir}."

# Create the file content.
tmpfile=`mktemp ${TMPDIR:-/tmp}/MV.XXXXXXX`
trap "rm -f ${tmpfile};" 0 1 2 3 15

if [ -n "${plain_version_string}" ]; then
    echo ${toolchain_version} > ${tmpfile}
else
    # Create a source file.
    cat > ${tmpfile} <<EOF
/* WARNING: Generated by "${progname}". */

#include <sys/types.h>
#include <libelftc.h>

const char *
elftc_version(void)
{
	return "${toolchain_version}";
}
EOF
fi

# Only replace the output file if its content changed.
if ! cmp -s ${tmpfile} ${versionfile}; then
    echo "@ ${progname}: building \"${versionfile}\"."
    cp ${tmpfile} ${versionfile} || exit ${?}
fi
